از مبانی کلاس و شی تا ارثبری و پروژههای عملی | آکادمی پایتون غیاثی
class python:
pass
class برای تعریف کلاس استفاده میشود. pass به عنوان یک جای خالی عمل میکند تا کلاس بدون خطا اجرا شود، ولی خودش کاری انجام نمیدهد.class pen:
pass
a = pen()
b = pen()
print(a)
print(b)
a و b دو شیء متفاوت هستند، پس آدرس حافظهٔ متفاوتی هم دارند.class pen:
pass
a = pen()
b = pen()
a.color = 'red'
a.size = 12
a.name = 'a001'
b.color = 'green'
b.size = 12
b.name = 'a001'
print(a.size) # خروجی: 12
class pen:
def __init__(self, color, size, name):
print(color)
print(size)
print(name)
print('--------------')
a = pen('green', 12, 'a001')
b = pen('red', 12, 'a001')
__init__ به صورت خودکار هنگام ساختن یک شیء جدید اجرا میشود. دیگر نیازی به خیره سازی دونه به دونه ویژگی ها نیست و لازم نیست تابع را جداگانه صدا بزنیم.class pen:
def __init__(self, color, size, name):
self.color = color
self.size = size
self.name = name
a = pen('green', 12, 'a001')
b = pen('red', 12, 'a001')
print(a.color) # خروجی: green
self به خود آن شیء اشاره میکند.self.color = color یعنی مقدار color که به تابع داده شده را در ویژگی color همان شیء ذخیره کن.a.color میتوانیم به مقدار ذخیره شده دسترسی پیدا کنیم.class info:
def __init__(self, fname, lname):
self.fname = fname
self.lname = lname
self.emil = f'{fname}_{lname}@gmil.com'
a = info('yasin', 'palangi')
b = info('mojtaba', 'sedaghatjo')
print(a.emil)
print(b.emil)
emil آن را چاپ کنیم.وقتی یک تابع داخل class قرار میگیرد، به آن متد میگوییم. متدها کارهایی هستند که شیء میتواند انجام دهد.
class info:
def __init__(self, fname, lname, age):
self.fname = fname
self.age = age
self.lname = lname
self.emil = f'{fname}_{lname}@gmil.com'
def bio(self):
return f'{self.fname} {self.lname} is {self.age} years old'
a = info('yasin', 'palangi', 21)
b = info('mojtaba', 'sedaghatjo', 45)
print(info.bio(a))
print(info.bio(b))
print(a.bio()) و print(b.bio()). این روش خواناتر و حرفهایتر است.فرض کنید شما یک «نقشه» یا «قالب» برای ساختن یک ساختمان دارید. بعداً شخص دیگری میآید و میگوید: «من هم همین نقشه را میخواهم، ولی باید یک پارکینگ هم به آن اضافه کنم.» در برنامهنویسی، به جای اینکه کل کد را از صفر بنویسیم، از همان کلاس قبلی ارثبری میکنیم و فقط قسمت جدید را اضافه میکنیم.
ابتدا یک کلاس ساده به نام mybilding میسازیم که ویژگیهای آدرس، تعداد طبقات و مساحت را دارد و یک متد برای نمایش مشخصات.
class mybilding:
def __init__(self, adress, floor, area):
self.adress = adress
self.floor = floor
self.area = area
def biography(self):
a = f'there is a bilding at {self.adress} the area is : {self.area} .with {self.floor} floors'
return a
first = mybilding('iran_bushehr', 12, 100)
print(first.biography())
first با آدرس «ایران_بوشهر»، ۱۲ طبقه و مساحت ۱۰۰ متر ساخته شده و متد biography() یک رشتهٔ توصیفی را برمیگرداند.حالا میخواهیم یک کلاس جدید بسازیم که تمام ویژگیهای کلاس بالا را داشته باشد و یک ویژگی جدید به نام parking (تعداد جای پارک) به آن اضافه کند. اینجا از ارثبری استفاده میکنیم.
class myfrindbilding(mybilding):
def __init__(self, adress, floor, area, parking):
super().__init__(adress, floor, area)
self.parking = parking
second = myfrindbilding('iran_tehran', 23, 20000, 20)
print('تعداد پارکینگ:', second.parking)
print(second.biography())
class myfrindbilding(mybilding): یعنی کلاس جدید از کلاس mybilding ارث میبرد.super() به کلاس والد اشاره دارد. با super().__init__(...) سازندهٔ کلاس والد را صدا میزنیم تا ویژگیهای آدرس، طبقه و مساحت مقداردهی شوند.self.parking را اضافه میکنیم.biography) به صورت خودکار در کلاس فرزند قابل استفاده است.در پایتون، یک کلاس میتواند از چند کلاس به طور همزمان ارثببرد. به این کار «ارثبری چندگانه» میگویند.
class a:
def __init__(self):
print('a class')
class b:
def __init__(self):
print('b class')
class c(a, b):
def __init__(self):
super().__init__()
print('c class')
ins = c()
print(ins)
class c(a,b) ابتدا از a و سپس از b ارث میبرد. اما تابع super() فقط سازندهٔ اولین کلاس (یعنی a) را فراخوانی میکند. به همین دلیل پیام 'b class' چاپ نمیشود.برای اینکه همهٔ کلاسهای والد مقداردهی شوند، باید در هر کلاس نیز از super() استفاده کنیم تا زنجیرهوار همه فراخوانی شوند.
class a:
def __init__(self):
super().__init__()
print('a class')
class b:
def __init__(self):
super().__init__()
print('b class')
class c(b, a):
def __init__(self):
super().__init__()
print('c class')
ins = c()
class c(b,a):) مشخص میکند که کدام کلاس زودتر جستجو شود. تابع super() با پیروی از ترتیب حل ارثبری (MRO)، تمام کلاسهای والد را به ترتیب صدا میزند.class m:
def __init__(self, a, b):
self.a = a
self.b = b
def add(self):
return self.a + self.b
def sub(self):
return self.a - self.b
def mul(self):
return self.a * self.b
def div(self):
if self.b == 0:
print('error: division by zero is not allowed')
return None
return self.a / self.b
ins = m(10, 5)
print('جمع:', ins.add())
print('تفریق:', ins.sub())
print('ضرب:', ins.mul())
print('تقسیم:', ins.div())
__init__ دو عدد a و b را از کاربر میگیرد و در ویژگیهای شی ذخیره میکند.add حاصل جمع را برمیگرداند.sub تفریق را انجام میدهد.mul ضرب را محاسبه میکند.div ابتدا بررسی میکند مخرج صفر نباشد؛ اگر صفر بود خطا میدهد، در غیر این صورت تقسیم را انجام میدهد.راهنمایی: یک کلاس به نام ContactManager بسازید. در متد __init__ یک لیست خالی برای ذخیره مخاطبان ایجاد کنید. سپس متدهایی با نامهای add_contact، search_contact، delete_contact و show_all طراحی کنید. برای نمایش زیباتر میتوانید از حلقه و چاپ جدولی استفاده کنید.
قالب اولیه برای شروع:
class ContactManager:
def __init__(self):
self.contacts = []
def add_contact(self, name, phone, email=''):
# کد اضافه کردن مخاطب
pass
def search_contact(self, name):
# کد جستجو
pass
def delete_contact(self, name):
# کد حذف
pass
def show_all(self):
# نمایش همه مخاطبان
pass
manager = ContactManager()
manager.add_contact('یاسین', '09123456789', 'yasin@example.com')
manager.show_all()
در این راهحل، از دو کلاس استفاده کردهایم:
برنامه با یک حلقه while True منوی تعاملی به کاربر نشان میدهد و کاربر میتواند عملیات مورد نظر خود را انتخاب کند.
class Contact:
def __init__(self, name, phone):
self.name = name
self.phone = phone
class PhoneBook:
def __init__(self):
self.contacts = {}
def add(self, name, phone):
self.contacts[name] = Contact(name, phone)
print("مخاطب اضافه شد")
def delete(self, name):
if name in self.contacts:
del self.contacts[name]
print("مخاطب حذف شد")
else:
print("مخاطب پیدا نشد")
def search(self, name):
if name in self.contacts:
print(f"{name} : {self.contacts[name].phone}")
else:
print("مخاطب پیدا نشد")
def show(self):
if not self.contacts:
print("دفترچه تلفن خالی است")
else:
for name, contact in self.contacts.items():
print(f"{name} : {contact.phone}")
phonebook = PhoneBook()
while True:
print("\n--- دفترچه تلفن ---")
print("1. افزودن مخاطب")
print("2. جستجوی مخاطب")
print("3. نمایش همه مخاطبین")
print("4. حذف مخاطب")
print("5. خروج")
choice = input("انتخاب کنید: ")
if choice == "1":
name = input("نام را وارد کنید: ")
phone = input("شماره تلفن را وارد کنید: ")
phonebook.add(name, phone)
elif choice == "2":
name = input("نام مخاطب را وارد کنید: ")
phonebook.search(name)
elif choice == "3":
phonebook.show()
elif choice == "4":
name = input("نام مخاطب برای حذف: ")
phonebook.delete(name)
elif choice == "5":
print("خروج از برنامه")
break
else:
print("گزینه نامعتبر است")
self.name و self.phone ذخیره میکند.__init__: یک دیکشنری خالی به نام self.contacts میسازد. کلید دیکشنری نام مخاطب و مقدار آن شیء Contact است.add(self, name, phone): یک مخاطب جدید با نام و شماره میسازد و به دیکشنری اضافه میکند.delete(self, name): ابتدا بررسی میکند آیا مخاطب با این نام وجود دارد یا نه. اگر وجود داشت، آن را حذف میکند.search(self, name): مخاطب را جستجو میکند و اگر پیدا شد، نام و شماره را چاپ میکند.show(self): اگر دیکشنری خالی باشد پیغام مناسب میدهد، در غیر این صورت همه مخاطبان را به همراه شماره چاپ میکند.phonebook صدا زده میشود.while True و شرطهای if/elif/else یک رابط کاربری ساده و کاربردی ساختهاند.class Child(Parent): و super() از کلاس والد استفاده مجدد میکنیم.super() مهم است.